#include "TcpServer.hpp"


TcpServer::TcpServer()
{

    listenFd_ = socket(AF_INET,SOCK_STREAM, 0);
    if (listenFd_ == -1) {
        perror("socket error");
        exit(-1);
    }

    int opt = 1;
    int ret = setsockopt(listenFd_, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt)); // 设置端口复用
    if (ret == -1) {
        perror("setsockopt error");
        exit(-1);
    }
}

int TcpServer::setListen(unsigned short port) {
    // sock_fd是用于连接的fd，把ip和端口bind上去
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET; //ipv4
    saddr.sin_addr.s_addr = INADDR_ANY; //inet_addr("xxx");
    saddr.sin_port = htons(port);
    int ret = bind(listenFd_, (sockaddr*)&saddr, sizeof(saddr)); //绑定端口和ip
    if (ret == -1) {
        perror("bind error");
        return -1;
    }

    ret = listen(listenFd_, SOMAXCONN); // 设置最大监听数量
    if (ret == -1) {
        perror("listen error");
        return -1;
    }
    return ret;

}


TcpServer::~TcpServer() {
    close(listenFd_);
}

void TcpServer::connectionCallBack(ConnectionPtr conn) {
    // accept,创建新的通信fd
    struct sockaddr_in caddr;
    unsigned int caddr_len = sizeof(caddr);
    int con_fd = accept(conn->getFd(), (sockaddr*) &caddr, &caddr_len);
    if (con_fd == -1) {
        perror("accept error");
        return ;
    }
    // std::cout << "[connection] ip: " << inet_ntoa(caddr.sin_addr) << ", port: " << caddr.sin_port << std::endl;
    auto callbackptr = std::make_shared<std::function<void(ConnectionPtr)>>(std::bind(&TcpServer::messageCallBack, this, std::placeholders::_1));
    eventLoop_.addEvent(con_fd, EPOLLIN | EPOLLOUT | EPOLLET, callbackptr);

    // 调用用户的处理函数
    if (userConnectionCall_) (*userConnectionCall_)(conn);
}


void TcpServer::messageCallBack(ConnectionPtr conn) {
    // 将内容读取到conn的buffer中
    int rlen = conn -> readSocket();
    if (rlen <= 0) {
        conn -> closeConnection();
        return ;

    }
    // 调用用户的处理函数，让用户自行处理conn中的buffer数据，并自行将返回结果写回conn中
    if (userMessageCall_) (*userMessageCall_)(conn);

    // 以下为测试代码
    // std::string str = "HTTP/1.1 200 OK\r\ncontent-length: 10\r\n\r\n01234";
    // std::string str2 = "HTTP/1.1 200 OK\r\ncontent-length: 10\r\n\r\n01234";
    // conn->writeToBuffer(std::vector<char>(str.begin(), str.end()));
    // conn->writeSocket();
    // conn->writeToBuffer(std::vector<char>(str2.begin(), str2.end()));
    // conn->writeSocket();
    // conn->closeConnection();
    
}


void TcpServer::start(unsigned short port) {
    int ret = setListen(port);
    if (ret == -1) {
        perror("setListen error");
        return ;
    }
    auto callbackptr = std::make_shared<std::function<void(ConnectionPtr)>>(std::bind(&TcpServer::connectionCallBack, this, std::placeholders::_1));
    eventLoop_.addEvent(listenFd_, EPOLLIN|EPOLLET, callbackptr);
    eventLoop_.run();
}
